package com.smart.manager.product.repository;


import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.smart.common.cache.CacheService;
import com.smart.common.entities.constant.ArcoTips;
import com.smart.common.entities.core.Page;
import com.smart.common.entities.domain.TaskResult;
import com.smart.common.entities.option.SelectOption;
import com.smart.manager.product.entities.body.RBasicCamera;
import com.smart.manager.product.entities.models.BasicCamera;
import com.smart.manager.product.entities.models.query.QBasicCamera;
import com.smart.manager.task.CameraTask;
import io.ebean.annotation.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 游戏管理  摄像头
 *
 * @author leo
 * @date 2023/09/13
 */
@Service
@Log4j2
@RequiredArgsConstructor
public class BasicCameraRepository {

    private final CacheService cacheService;

    private final CameraTask cameraTask;

    /**
     *获取 直播地址
     */
    private final static String LIVE  = "https://open.ys7.com/api/lapp/v2/live/address/get";
    /**
     *修改设备名称地址
     */
    private final static String NAME  = "https://open.ys7.com/api/lapp/device/name/update";
    /**
     *修改设备OSD名称地址
     */
    private final static String OSD  = "https://open.ys7.com/api/lapp/device/update/osd/name";

    public Page<BasicCamera> pageList(RBasicCamera.SearchBody search) {
        QBasicCamera query = new QBasicCamera();
        Opt.ofBlankAble(search.getDeviceName()).ifPresent(x -> query.deviceName.contains(x));
        Opt.ofBlankAble(search.getDeviceSerial()).ifPresent(x -> query.deviceSerial.contains(x));
        query.setFirstRow(search.firstRow()).setMaxRows(search.maxRows());
        return new Page<BasicCamera>().load(query.findPagedList());
    }

    public void update(Long id, RBasicCamera.EditBody body) {
        BasicCamera record = getOneById(id);
        Assert.notNull(record, ArcoTips.UPDATE_NOT_FOUND);
        Opt.ofBlankAble(body.getDeviceName()).ifPresent(x->{
            updateName(record,x);
        });
        Opt.ofBlankAble(body.getOsdName()).ifPresent(x->{
            updateOsdName(record,x);
        });
    }


    /**
     * 获取摄像头直播地址
     *
     * @param id 摄像头id
     * @return {@link String}
     */
    public String getAddress(Long id,Boolean isRemind) {
        String url = cacheService.getCameraCache().get(id);
        if (StrUtil.isBlank(url)) {
            String accessToken = cacheService.getCameraTokenCache().get("accessToken");
            BasicCamera record = getOneById(id);
            Assert.notNull(record, ArcoTips.UPDATE_NOT_FOUND);
            Map<String, Object> map = Map.of("accessToken", accessToken, "deviceSerial", record.getDeviceSerial(), "protocol", 2, "expireTime", 8200);
            HttpResponse execute = HttpRequest.post(LIVE).form(map).execute();
            JSON parse = JSONUtil.parse(execute.body());
            log.warn("object=={}", parse);
            boolean code = ObjectUtil.equals(parse.getByPath("code"), "200");
            if (isRemind){
                Assert.isTrue(code, (String) parse.getByPath("msg"));
            }
            if (!code){
                return null;
            }
            url = (String) parse.getByPath("data.url");
            Opt.ofBlankAble(url).ifPresent(x -> cacheService.getCameraCache().put(id, x));
        }
        return url;
    }

    /**
     * 修改云端设备名称
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateName(BasicCamera record, String name) {
        if (ObjectUtil.equals(record.getDeviceName(), name)){
            return;
        }
        String accessToken = cacheService.getCameraTokenCache().get("accessToken");
//        BasicCamera record = getOneById(id);
        Assert.notNull(record, ArcoTips.UPDATE_NOT_FOUND);
        Map<String, Object> map = Map.of("accessToken", accessToken, "deviceSerial", record.getDeviceSerial(), "deviceName", name);
        HttpResponse execute = HttpRequest.post(NAME).form(map).execute();
        JSONObject object = new JSONObject(execute.body());
        log.warn("object=={}", object);
        record.setDeviceName(name).update();
        Assert.isTrue(ObjectUtil.equals(object.get("code"), "200"), (String) object.get("msg"));
    }

    /**
     * 修改云端设备Osd设备
     */
    public void updateOsdName(BasicCamera record, String title) {
        String accessToken = cacheService.getCameraTokenCache().get("accessToken");
//        BasicCamera record = getOneById(id);
        Assert.notNull(record, ArcoTips.UPDATE_NOT_FOUND);
        Map<String, Object> map = Map.of("accessToken", accessToken, "deviceSerial", record.getDeviceSerial(), "osdName", title);
        HttpResponse execute = HttpRequest.post(OSD).form(map).execute();
        JSONObject object = new JSONObject(execute.body());
        log.warn("object=={}", object);
        Assert.isTrue(ObjectUtil.equals(object.get("code"), "200"), (String) object.get("msg"));
    }


    /**
     * 关闭摄像头加密
     * TODO: 未完成
     */
    public void encryptOff(String deviceSerial) {
        String accessToken = cacheService.getCameraTokenCache().get("accessToken");
        Map<String, Object> map = Map.of("accessToken", accessToken, "deviceSerial",deviceSerial);
        HttpResponse execute = HttpRequest.post("https://open.ys7.com/api/lapp/device/encrypt/off").form(map).execute();
        JSONObject object = new JSONObject(execute.body());
        log.warn("object=={}", object);
        Assert.isTrue(ObjectUtil.equals(object.get("code"), "200"));
    }

    /**
     * 获取一个数据
     *
     * @param id id
     * @return {@link BasicCamera}
     */
    private BasicCamera getOneById(Long id) {
        QBasicCamera query = new QBasicCamera();
        BasicCamera record = query.id.eq(id).setMaxRows(1).findOne();
        Assert.notNull(record, ArcoTips.UPDATE_NOT_FOUND);
        return record;
    }

    /**
     * 刷新摄像头
     */
    public TaskResult refreshCamera(){
        return cameraTask.earTagData();
    }


    /**
     * 获取数据字典下拉选项
     * @return {@code List<SelectOption>}
     */
    public List<SelectOption> getOptions() {
        QBasicCamera place = new QBasicCamera().status.eq(1); //查找在线的摄像头并且是未绑定的
        return place.findStream()
                .map(x -> new SelectOption().setLabel(x.getDeviceName()).setValue(x.getDeviceSerial()).setDisabled(false))
                .collect(Collectors.toList());
    }


}






